9b0ff9
@@ -1,7 +1,5 @@
 package org.springframework.roo.shell.jline;
 
-
-import java.io.BufferedInputStream;
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
@@ -22,24 +20,24 @@
import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import jline.ANSIBuffer;
+import jline.ANSIBuffer.ANSICodes;
 import jline.ConsoleReader;
 import jline.WindowsTerminal;
-import jline.ANSIBuffer.ANSICodes;
 
 import org.springframework.roo.shell.AbstractShell;
 import org.springframework.roo.shell.CommandMarker;
 import org.springframework.roo.shell.ExitShellRequest;
 import org.springframework.roo.shell.Shell;
 import org.springframework.roo.shell.event.ShellStatus;
-import org.springframework.roo.shell.event.ShellStatusListener;
 import org.springframework.roo.shell.event.ShellStatus.Status;
+import org.springframework.roo.shell.event.ShellStatusListener;
 import org.springframework.roo.support.util.Assert;
 import org.springframework.roo.support.util.ClassUtils;
 import org.springframework.roo.support.util.OsUtils;
 import org.springframework.roo.support.util.StringUtils;
 
 /**
- * Uses the feature-rich <a href="http://jline.sourceforge.net/">JLine</a> library to provide an interactive shell.
+ * Uses the feature-rich <a href="http://sourceforge.net/projects/jline/">JLine</a> library to provide an interactive shell.
  * 
  * <p>
  * Due to Windows' lack of color ANSI services out-of-the-box, this implementation automatically detects the classpath
@@ -55,61 +53,63 @@
public abstract class JLineShell extends AbstractShell implements CommandMarker,
 	private static final boolean JANSI_AVAILABLE = ClassUtils.isPresent(ANSI_CONSOLE_CLASSNAME, JLineShell.class.getClassLoader());
 	private static final boolean APPLE_TERMINAL = Boolean.getBoolean("is.apple.terminal");
 	private static final char ESC = 27;
-	
-    private ConsoleReader reader;
-    private boolean developmentMode = false;
-    private FileWriter fileLog;
+
+	private ConsoleReader reader;
+	private boolean developmentMode = false;
+	private FileWriter fileLog;
 	private DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 	protected ShellStatusListener statusListener; // ROO-836
 	/** key: slot name, value: flashInfo instance */
 	private Map<String, FlashInfo> flashInfoMap = new HashMap<String, FlashInfo>();
 	/** key: row number, value: eraseLineFromPosition */
-	private Map<Integer,Integer> rowErasureMap = new HashMap<Integer,Integer>();
+	private Map<Integer, Integer> rowErasureMap = new HashMap<Integer, Integer>();
 	private boolean shutdownHookFired = false; // ROO-1599
-	
+
 	public void run() {
 		try {
 			if (JANSI_AVAILABLE && OsUtils.isWindows()) {
 				try {
 					reader = createAnsiWindowsReader();
 				} catch (Exception e) {
-					// Try again using default ConsoleReader constructor 
+					// Try again using default ConsoleReader constructor
 					logger.warning("Can't initialize jansi AnsiConsole, falling back to default: " + e);
 				}
 			}
-			if (reader == null) reader = new ConsoleReader();
+			if (reader == null) {
+				reader = new ConsoleReader();
+			}
 		} catch (IOException ioe) {
 			throw new IllegalStateException("Cannot start console class", ioe);
 		}
-		
+
 		setPromptPath(null);
-		
-        JLineLogHandler handler = new JLineLogHandler(reader, this);
-        JLineLogHandler.prohibitRedraw(); // affects this thread only
+
+		JLineLogHandler handler = new JLineLogHandler(reader, this);
+		JLineLogHandler.prohibitRedraw(); // Affects this thread only
 		Logger mainLogger = Logger.getLogger("");
-        removeHandlers(mainLogger);
-        mainLogger.addHandler(handler);
+		removeHandlers(mainLogger);
+		mainLogger.addHandler(handler);
+
+		reader.addCompletor(new JLineCompletorAdapter(getParser()));
 
-        reader.addCompletor(new JLineCompletorAdapter(getParser()));
-		
 		reader.setBellEnabled(true);
 		if (Boolean.getBoolean("jline.nobell")) {
-        	reader.setBellEnabled(false);
+			reader.setBellEnabled(false);
 		}
-                
+
 		// reader.setDebug(new PrintWriter(new FileWriter("writer.debug", true)));
-		
+
 		openFileLogIfPossible();
-		
+
 		flashMessageRenderer();
-		
-        logger.info(version(null));
 
-        flash(Level.FINE, "Spring Roo " + versionInfo(), Shell.WINDOW_TITLE_SLOT);
-        
-        logger.info("Welcome to Spring Roo. For assistance press " + completionKeys + " or type \"hint\" then hit ENTER.");
-        
-        setShellStatus(Status.STARTED);
+		logger.info(version(null));
+
+		flash(Level.FINE, "Spring Roo " + versionInfo(), Shell.WINDOW_TITLE_SLOT);
+
+		logger.info("Welcome to Spring Roo. For assistance press " + completionKeys + " or type \"hint\" then hit ENTER.");
+
+		setShellStatus(Status.STARTED);
 
 		// Monitor CTRL+C initiated shutdowns (ROO-1599)
 		Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@@ -118,22 +118,22 @@
public abstract class JLineShell extends AbstractShell implements CommandMarker,
 				// We don't need to closeShell(), as the shutdown hook in o.s.r.bootstrap.Main calls stop() which calls JLineShellComponent.deactivate() and that calls closeShell()
 			}
 		}, "Spring Roo JLine Shutdown Hook"));
-        
-        // Handle any "execute-then-quit" operation
-        String rooArgs = System.getProperty("roo.args");
-        if (rooArgs != null && !"".equals(rooArgs)) {
-            setShellStatus(Status.USER_INPUT);
-        	boolean success = executeCommand(rooArgs);
-            if (exitShellRequest == null) {
-            	// The command itself did not specify an exit shell code, so we'll fall back to something sensible here
-                executeCommand("quit"); // ROO-839
-               	exitShellRequest = success ? ExitShellRequest.NORMAL_EXIT : ExitShellRequest.FATAL_EXIT;
-            }
-            setShellStatus(Status.SHUTTING_DOWN);
-        } else {
-            // Normal RPEL processing
-        	promptLoop();
-        }
+
+		// Handle any "execute-then-quit" operation
+		String rooArgs = System.getProperty("roo.args");
+		if (rooArgs != null && !"".equals(rooArgs)) {
+			setShellStatus(Status.USER_INPUT);
+			boolean success = executeCommand(rooArgs);
+			if (exitShellRequest == null) {
+				// The command itself did not specify an exit shell code, so we'll fall back to something sensible here
+				executeCommand("quit"); // ROO-839
+				exitShellRequest = success ? ExitShellRequest.NORMAL_EXIT : ExitShellRequest.FATAL_EXIT;
+			}
+			setShellStatus(Status.SHUTTING_DOWN);
+		} else {
+			// Normal RPEL processing
+			promptLoop();
+		}
 	}
 
 	private void removeHandlers(Logger l) {
@@ -144,8 +144,8 @@
public abstract class JLineShell extends AbstractShell implements CommandMarker,
 			}
 		}
 	}
-	
-	@Override 
+
+	@Override
 	public void setPromptPath(String path) {
 		if (reader.getTerminal().isANSISupported()) {
 			ANSIBuffer ansi = JLineLogHandler.getANSIBuffer();
@@ -155,11 +155,11 @@
public abstract class JLineShell extends AbstractShell implements CommandMarker,
 				shellPrompt = ansi.cyan(path).yellow(" roo> ").toString();
 			}
 		} else {
-			// the superclass will do for this non-ANSI terminal
+			// The superclass will do for this non-ANSI terminal
 			super.setPromptPath(path);
 		}
 
-		// the shellPrompt is now correct; let's ensure it now gets used
+		// The shellPrompt is now correct; let's ensure it now gets used
 		reader.setDefaultPrompt(JLineShell.shellPrompt);
 	}
 
@@ -181,17 +181,11 @@
public abstract class JLineShell extends AbstractShell implements CommandMarker,
 			}
 		};
 		addShellStatusListener(statusListener);
-		return new ConsoleReader(
-			new BufferedInputStream(new FileInputStream(FileDescriptor.in)),
-        	new PrintWriter(
-        		new OutputStreamWriter(ansiOut,
-        			// Default to Cp850 encoding for Windows console output (ROO-439)
-        			System.getProperty("jline.WindowsTerminal.output.encoding", "Cp850"))),
-    		null,
-			ansiTerminal
-		);
+		return new ConsoleReader(new FileInputStream(FileDescriptor.in), new PrintWriter(new OutputStreamWriter(ansiOut,
+		// Default to Cp850 encoding for Windows console output (ROO-439)
+				System.getProperty("jline.WindowsTerminal.output.encoding", "Cp850"))), null, ansiTerminal);
 	}
-	
+
 	private void flashMessageRenderer() {
 		if (!reader.getTerminal().isANSISupported()) {
 			return;
@@ -202,11 +196,11 @@
public abstract class JLineShell extends AbstractShell implements CommandMarker,
 				while (!shellStatus.getStatus().equals(Status.SHUTTING_DOWN) && !shutdownHookFired) {
 					synchronized (flashInfoMap) {
 						long now = System.currentTimeMillis();
-						
+
 						Set<String> toRemove = new HashSet<String>();
 						for (String slot : flashInfoMap.keySet()) {
 							FlashInfo flashInfo = flashInfoMap.get(slot);
-							
+
 							if (flashInfo.flashMessageUntil < now) {
 								// Message has expired, so clear it
 								toRemove.add(slot);
@@ -222,62 +216,63 @@
public abstract class JLineShell extends AbstractShell implements CommandMarker,
 					}
 					try {
 						Thread.sleep(200);
-					} catch (InterruptedException ignore) {}
+					} catch (InterruptedException ignore) {
+					}
 				}
 			}
 		}, "Spring Roo JLine Flash Message Manager");
 		t.start();
 	}
-	
+
 	public void flash(Level level, String message, String slot) {
 		Assert.notNull(level, "Level is required for a flash message");
 		Assert.notNull(message, "Message is required for a flash message");
 		Assert.hasText(slot, "Slot name must be specified for a flash message");
-		
+
 		if (Shell.WINDOW_TITLE_SLOT.equals(slot)) {
-    		if (reader != null && reader.getTerminal().isANSISupported()) {
-            	// We can probably update the window title, as requested
-			    if (!StringUtils.hasText(message)) {
-				    System.out.println("No text");
-			    }
-
-        		ANSIBuffer buff = JLineLogHandler.getANSIBuffer();
-			    String suffix = "\\";
-			    if (APPLE_TERMINAL) {
+			if (reader != null && reader.getTerminal().isANSISupported()) {
+				// We can probably update the window title, as requested
+				if (!StringUtils.hasText(message)) {
+					System.out.println("No text");
+				}
+
+				ANSIBuffer buff = JLineLogHandler.getANSIBuffer();
+				String suffix = "\\";
+				if (APPLE_TERMINAL) {
 					suffix = "";
-			    }
-    			buff.append(ESC + "]0;").append(message).append(ESC + suffix);
-        		String stg = buff.toString();
-        		try {
-        			reader.printString(stg);
-        			reader.flushConsole();
-        		} catch (IOException ignore) {}
-        	}
-			
-    		return;
+				}
+				buff.append(ESC + "]0;").append(message).append(ESC + suffix);
+				String stg = buff.toString();
+				try {
+					reader.printString(stg);
+					reader.flushConsole();
+				} catch (IOException ignore) {
+				}
+			}
+
+			return;
 		}
-		if ((reader !=null && !reader.getTerminal().isANSISupported())) {
+		if ((reader != null && !reader.getTerminal().isANSISupported())) {
 			super.flash(level, message, slot);
 			return;
 		}
 		synchronized (flashInfoMap) {
 			FlashInfo flashInfo = flashInfoMap.get(slot);
-			
+
 			if ("".equals(message)) {
 				// Request to clear the message, but give the user some time to read it first
 				if (flashInfo == null) {
 					// We didn't have a record of displaying it in the first place, so just quit
 					return;
 				}
-	    		flashInfo.flashMessageUntil = System.currentTimeMillis() + 1500;
+				flashInfo.flashMessageUntil = System.currentTimeMillis() + 1500;
 			} else {
-	    		// Display this message displayed until further notice
+				// Display this message displayed until further notice
 				if (flashInfo == null) {
 					// Find a row for this new slot; we basically take the first line number we discover
 					flashInfo = new FlashInfo();
 					flashInfo.rowNumber = Integer.MAX_VALUE;
-					outer:
-					for (int i = 1; i < Integer.MAX_VALUE; i++) {
+					outer: for (int i = 1; i < Integer.MAX_VALUE; i++) {
 						for (FlashInfo existingFlashInfo : flashInfoMap.values()) {
 							if (existingFlashInfo.rowNumber == i) {
 								// Veto, let's try the new candidate row number
@@ -288,7 +283,7 @@
public abstract class JLineShell extends AbstractShell implements CommandMarker,
 						flashInfo.rowNumber = i;
 						break outer;
 					}
-					
+
 					// Store it
 					flashInfoMap.put(slot, flashInfo);
 				}
@@ -319,14 +314,14 @@
public abstract class JLineShell extends AbstractShell implements CommandMarker,
 				mostFurtherLeftColNumber = candidate;
 			}
 		}
-		
+
 		if (mostFurtherLeftColNumber == Integer.MAX_VALUE) {
 			// There is nothing to erase
 		} else {
 			buff.append(ANSICodes.gotoxy(row, mostFurtherLeftColNumber));
 			buff.append(ANSICodes.clreol()); // clear what was present on the line
 		}
-		
+
 		if (("".equals(message))) {
 			// They want the line blank; we've already achieved this if needed via the erasing above
 			// Just need to record we no longer care about this line the next time doAnsiFlash is invoked
@@ -355,56 +350,58 @@
public abstract class JLineShell extends AbstractShell implements CommandMarker,
 		try {
 			reader.printString(stg);
 			reader.flushConsole();
-		} catch (IOException ignore) {}
+		} catch (IOException ignore) {
+		}
+	}
+
+	public void promptLoop() {
+		setShellStatus(Status.USER_INPUT);
+		String line;
+
+		try {
+			while (exitShellRequest == null && ((line = reader.readLine()) != null)) {
+				JLineLogHandler.resetMessageTracking();
+				setShellStatus(Status.USER_INPUT);
+
+				if ("".equals(line)) {
+					continue;
+				}
+
+				executeCommand(line);
+			}
+		} catch (IOException ioe) {
+			throw new IllegalStateException("Shell line reading failure", ioe);
+		}
+
+		setShellStatus(Status.SHUTTING_DOWN);
 	}
-	
-    public void promptLoop() {
-    	setShellStatus(Status.USER_INPUT);
-    	String line;
-    	
-    	try {
-            while (exitShellRequest == null && ( (line = reader.readLine() ) != null) ) {
-            	JLineLogHandler.resetMessageTracking();
-            	setShellStatus(Status.USER_INPUT);
-            	
-            	if ("".equals(line)) {
-                	continue;
-                }
-            	
-                executeCommand(line);
-            }
-        } catch (IOException ioe) {
-        	throw new IllegalStateException("Shell line reading failure", ioe);
-        }
-        
-        setShellStatus(Status.SHUTTING_DOWN);
-    }
-    
+
 	public void setDevelopmentMode(boolean developmentMode) {
 		JLineLogHandler.setIncludeThreadName(developmentMode);
-		JLineLogHandler.setSuppressDuplicateMessages(!developmentMode); // we want to see duplicate messages during development time (ROO-1873)
+		JLineLogHandler.setSuppressDuplicateMessages(!developmentMode); // We want to see duplicate messages during development time (ROO-1873)
 		this.developmentMode = developmentMode;
 	}
 
 	public boolean isDevelopmentMode() {
 		return this.developmentMode;
 	}
-	
+
 	private void openFileLogIfPossible() {
 		try {
 			fileLog = new FileWriter("log.roo", true);
 			// First write, so let's record the date and time of the first user command
 			fileLog.write("// Spring Roo " + versionInfo() + " log opened at " + df.format(new Date()) + "\n");
 			fileLog.flush();
-		} catch (IOException ignoreIt) {}
+		} catch (IOException ignoreIt) {
+		}
 	}
-	
+
 	@Override
 	protected void logCommandToOutput(String processedLine) {
 		if (fileLog == null) {
 			openFileLogIfPossible();
 			if (fileLog == null) {
-				// still failing, so give up
+				// Still failing, so give up
 				return;
 			}
 		}
@@ -418,12 +415,13 @@
public abstract class JLineShell extends AbstractShell implements CommandMarker,
 				fileLog.close();
 				fileLog = null;
 			}
-		} catch (IOException ignoreIt) {}
+		} catch (IOException ignoreIt) {
+		}
 	}
 
 	/**
 	 * Obtains the "roo.home" from the system property, falling back to the current working directory if missing.
-	 *
+	 * 
 	 * @return the 'roo.home' system property
 	 */
 	@Override
@@ -438,7 +436,7 @@
public abstract class JLineShell extends AbstractShell implements CommandMarker,
 		}
 		return rooHome;
 	}
-	
+
 	/**
 	 * Should be called by a subclass before deactivating the shell.
 	 */
